package com.fingard.dsp.distribute.bocom12;

import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Date;
import java.util.concurrent.atomic.AtomicInteger;

import com.fingard.FGBiz;
import com.fingard.constant.Format;
import com.fingard.dsp.distribute.dstrbset.DstrbItem;
import com.fingard.io.FileHelper;
import com.fingard.net.TcpReceiver;
import com.fingard.text.StringHelper;
import com.fingard.xml.XmlTextReader;

public class BOCOM12Dispatcher implements Runnable{
	private DstrbItem dstrbItem;
	private int listenType = 0;
	private int portType = 0;
	private Socket clientSocket;
	/**
	 * @param p_listenType 1接收客户端，发服务器，2接收服务端，发客户端
	 * @param p_portType 1联机交易，2文件
	 * */
	public BOCOM12Dispatcher(DstrbItem p_dstrbItem, int p_listenType, int p_portType,Socket p_socket) {
		dstrbItem = p_dstrbItem;
		listenType = p_listenType;
		portType=p_portType;
		clientSocket = p_socket;
	}
	
	public int listenPort = 0;
	public int seqIDInner = 0;
	
	public void run() {
		try {
			doRequest();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	private TcpReceiver recBytesFromSocket(Socket p_socket){
		TcpReceiver retReceiver = new TcpReceiver();
		try {
			InputStream tmpInput = p_socket.getInputStream();
			
			retReceiver.recBytes = new byte[2048];//2K
			int tmpOffSet = 0;
            
			while(!retReceiver.isCompleted){
				int tmpReadLen = tmpInput.read(retReceiver.recBytes, tmpOffSet, retReceiver.recBytes.length - tmpOffSet);
				if(tmpReadLen<=0){
					break;
				}
				tmpOffSet += tmpReadLen;
				retReceiver.readedLength = retReceiver.readedLength + tmpReadLen;
				if(retReceiver.contentLength == -1){
					//通讯头部
					if(retReceiver.readedLength>=8){
						String tmpHead = new String(retReceiver.recBytes,0,8,"utf-8");
						retReceiver.contentLength = Integer.parseInt(tmpHead);
						retReceiver.contentStartIndex=8;
					}
					//end
				}
				
				if (retReceiver.contentLength > 0)
                {
                    if (retReceiver.recBytes.length < retReceiver.contentLength + retReceiver.contentStartIndex)
                    {
                        byte[] tmpUnionInfo = new byte[retReceiver.contentLength + retReceiver.contentStartIndex];//一次性分配内存
        				System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo, 0, tmpOffSet);
        				retReceiver.recBytes = null;
        				retReceiver.recBytes = tmpUnionInfo;
                    }
                    
                    int tmpToReadLen = retReceiver.contentLength + retReceiver.contentStartIndex - tmpOffSet;
                    if (tmpToReadLen <= 0)
                    {
                    	retReceiver.isCompleted = true;
                    	break;
                    }
                }
				else if(retReceiver.recBytes.length - tmpOffSet < 1024){//扩展
					byte[] tmpUnionInfo2 = new byte[tmpOffSet + 20480];
					System.arraycopy(retReceiver.recBytes, 0, tmpUnionInfo2, 0, tmpOffSet);
					retReceiver.recBytes = null;
					retReceiver.recBytes = tmpUnionInfo2;
				}
			}
		}
		catch (IOException e) {
			e.printStackTrace();
			retReceiver.connMsg = e.getMessage();
		}
		return retReceiver;
	}
	

	private static AtomicInteger concurrentNum = new AtomicInteger();
	private static int maxConcurrent = 0;
	private static Date maxHappenedTime = new Date();

	private void doRequest() throws Exception{
		
		int tmpConcurrentNum = concurrentNum.incrementAndGet();
		if(tmpConcurrentNum>maxConcurrent){
			maxConcurrent=tmpConcurrentNum;
			maxHappenedTime = new Date();
		    System.out.println("侦听端口"+listenPort+"当前并发数："+tmpConcurrentNum);
		}
		Date tmpTimeNow = new Date();
		StringBuilder sbLog = new StringBuilder();
		Socket dstrbSocket = null;
		try {
			
			int recLoopCount = 1;
			
			
			sbLog.append(Format.DateTimeSSSFormat.format(tmpTimeNow)+" 1.开始接收\r\n");
			
			TcpReceiver recClient = recBytesFromSocket(clientSocket);
			if(recClient.readedLength==0){//recClient.readedLength==0是F5等探测
				clientSocket.close();
				clientSocket = null;
				return;
			}
			String tmpStrRec = new String(recClient.recBytes,0,recClient.readedLength,"utf-8");
			sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 1.接收到请求"+recClient.readedLength+"字节："+tmpStrRec+"\r\n");
			
			String strReqXmlHead = "";
			String fileType = "";
			boolean isBatPayRec = false;
			if(recClient.isCompleted && recClient.readedLength>=30){
				if(portType == 2){//文件
					//String transCode1 = new String(recClient.recBytes,24,6,"utf-8");
					//if(transCode1.equals("B60901")||transCode1.equals("I60901") || transCode1.equals("B60902")||transCode1.equals("I60902")){
					
					//String tmpFileName = new String(recClient.recBytes, 114, 128).trim();//压缩文件名称
					
						if(recClient.readedLength>=150){//取文件类型
							fileType = new String(recClient.recBytes,147,3,"utf-8");
						}
					//}
				}
				else{
					int tmpIndex = tmpStrRec.indexOf("<");
					XmlTextReader xmlReader = new XmlTextReader(tmpStrRec.substring(tmpIndex));
					strReqXmlHead = xmlReader.getOuterXml("/Req/Head");
					
					String tmpFileName = xmlReader.getFirstText("/Req/Body/FileName");
					if(StringHelper.hasAnyChar(tmpFileName)){
						tmpFileName = tmpFileName.trim();
						fileType = tmpFileName.substring(33, 36);
					}
					//String TrCode = xmlReader.getFirstText("/Req/Head/TrCode");
					//if(TrCode != null){
						//if(TrCode.equals("B60901")||TrCode.equals("I60901") || TrCode.equals("B60902")||TrCode.equals("I60902")||TrCode.equals("B60903")||TrCode.equals("I60903")||TrCode.equals("B60904")||TrCode.equals("I60904")){
							//fileType = xmlReader.getFirstText("/Req/Body/FileType");
						//}
					//}
				}
			}
			if(fileType.equals("I11") || fileType.equals("I12")){//批量代收付文件
				isBatPayRec = true;
			}
			
			
			String tmpConnMsg = "";
			
			try{
				if(listenType == 1){//1接收客户端，发服务器
					if(portType == 2){//文件
						dstrbSocket = new Socket(dstrbItem.bankIP, Integer.parseInt(dstrbItem.bankFilePort));
						sbLog.append("转发至银行文件端口"+dstrbItem.bankIP+":"+dstrbItem.bankFilePort+"\r\n");
					}
					else{
						dstrbSocket = new Socket(dstrbItem.bankIP, Integer.parseInt(dstrbItem.bankPort));
						sbLog.append("转发至银行联机交易端口"+dstrbItem.bankIP+":"+dstrbItem.bankPort+"\r\n");
					}
				}
				else if(listenType == 2){//2接收服务端，发客户端
					if(portType == 2){//文件
						if(isBatPayRec){
							dstrbSocket = new Socket(dstrbItem.dspIP, Integer.parseInt(dstrbItem.dspFilePort));
							sbLog.append("转发至DSP文件端口"+dstrbItem.dspIP+":"+dstrbItem.dspFilePort+"\r\n");
						}
						else{
							dstrbSocket = new Socket(dstrbItem.insuIP, Integer.parseInt(dstrbItem.insuFilePort));
							sbLog.append("转发至银保文件端口"+dstrbItem.insuIP+":"+dstrbItem.insuFilePort+"\r\n");
						}
					}
					else{
						if(isBatPayRec){
							dstrbSocket = new Socket(dstrbItem.dspIP, Integer.parseInt(dstrbItem.dspPort));
							sbLog.append("转发至DSP联机交易端口"+dstrbItem.dspIP+":"+dstrbItem.dspPort+"\r\n");
						}
						else{
							dstrbSocket = new Socket(dstrbItem.insuIP, Integer.parseInt(dstrbItem.insuPort));
							sbLog.append("转发至银保联机交易端口"+dstrbItem.insuIP+":"+dstrbItem.insuPort+"\r\n");
						}
					}
				}
				dstrbSocket.setSoTimeout(120000);
			}
			catch(Exception ex){
				tmpConnMsg = ex.getMessage();
				sbLog.append(ex.getMessage()+"\r\n");
			}
			
			DataOutputStream clientOutput = new DataOutputStream(clientSocket.getOutputStream());
			if(tmpConnMsg.length()>0){
				
				
				String retStr = "";
				if(portType == 1){
					
					if(StringHelper.isNullOrEmpty(strReqXmlHead)){
						strReqXmlHead = "";
					}
					StringBuilder sbHead = new StringBuilder();
					if(strReqXmlHead.indexOf("<Head>")>=0){
						sbHead.append(strReqXmlHead.substring(0,strReqXmlHead.indexOf("<Head>")+6));
						sbHead.append("<MsgType>E</MsgType>");
						sbHead.append("<ErrCode>E99999</ErrCode>");
						sbHead.append("<ErrMsg>"+tmpConnMsg+"</ErrMsg>");
						sbHead.append(strReqXmlHead.substring(strReqXmlHead.indexOf("<Head>")+6));
						strReqXmlHead = sbHead.toString();
					}
					retStr = "****************<?xml version=\"1.0\" encoding=\"utf-8\"?><Rsp>"+strReqXmlHead+"<Body></Body></Rsp>";
				}
				else{
					retStr = StringHelper.padLeftUTF8Byte("A000003", 23,'*')+StringHelper.padRightUTF8Byte(tmpConnMsg, 328, ' ');
				}
				sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 4.返回："+retStr+"\r\n");
				
				byte[] retBytes = retStr.getBytes("utf-8");
				String bodyLen = StringHelper.padLeftUTF8Byte(String.valueOf(retBytes.length),8,'0');
				retStr = bodyLen+retStr;
				retBytes = retStr.getBytes("utf-8");
				clientOutput.write(retBytes);
			}
			else{
				
				while(true){
					String transCode = "";//交易码
					if(recLoopCount>1){
						recClient = recBytesFromSocket(clientSocket);//第一次已被上面接收
					}
					recLoopCount++;
					if(recClient.readedLength<=0){
						break;
					}
					if(recClient.isCompleted && recClient.readedLength>=30){
						if(portType == 2){
							transCode = new String(recClient.recBytes,24,6,"utf-8");
						}
						
						if(recLoopCount>1){//第一次日志已输出
							sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 1-"+recLoopCount+".接收到请求："+recClient.readedLength+"字节，交易代码："+transCode+"\r\n");
							if(recClient.readedLength>=24){
								sbLog.append("头部："+new String(recClient.recBytes,0,24,"utf-8")+"\r\n");
							}
						}
					}
					
					//转发
					TcpReceiver recServer = sendToServer(dstrbSocket,recClient,sbLog);
					if(recServer.readedLength<=0){
						break;
					}
					if(recServer.isCompleted && recServer.readedLength>=30){
						if(portType == 2){
							transCode = new String(recServer.recBytes,24,7,"utf-8");
							sbLog.append("响应代码："+transCode+"\r\n");
						}
					}
					//转发结束
					
					clientOutput.write(recServer.recBytes, 0, recServer.readedLength);
					sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 4.返回响应："+recServer.readedLength+"字节完成\r\n");
					
				}
				dstrbSocket.close();
				dstrbSocket = null;
			}
		
			
			
			clientSocket.close();
			clientSocket = null;

		} catch (IOException e) {
			e.printStackTrace();
			sbLog.append(e.getMessage()+"\r\n");
		}
		finally{

			tmpConcurrentNum = concurrentNum.decrementAndGet();
			if(tmpConcurrentNum==0){
				Date tmpTimeFin = new Date();
				long tmpMilSeconds = tmpTimeFin.getTime() - maxHappenedTime.getTime();
				long tmpSeconds = tmpMilSeconds / 1000;
				if(tmpSeconds>=60){
					maxConcurrent =0 ;
					System.out.println("当前并发数："+tmpConcurrentNum);
				}
			}
			if(dstrbSocket != null){
				dstrbSocket.close();
			}
			if(clientSocket != null){
				clientSocket.close();
			}
		}
		try{
		String tmpStrLogSeq = String.format("%04d", seqIDInner);
		String tmpDateDir = Format.DateForLogFormat.format(tmpTimeNow).replace("-", File.separator);
		String tmpLogFile = FGBiz.distributor.logsDirPath+File.separator+dstrbItem.dstrbCode+"Logs"+File.separator+tmpDateDir+File.separator+listenPort+"_"+Format.DateTime14Format.format(tmpTimeNow)+"_"+tmpStrLogSeq+".txt";
		FileHelper.writeFile(tmpLogFile, sbLog);
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	private TcpReceiver sendToServer(Socket dstrbSocket, TcpReceiver toSend, StringBuilder sbLog) throws IOException{
		OutputStream dstrbOutput = dstrbSocket.getOutputStream();//转发
		dstrbOutput.write(toSend.recBytes, 0, toSend.readedLength);
		
		//sbLog.append("-----转发内容-----\r\n" + new String(toSend.recBytes,0,toSend.readedLength,"utf-8")+"\r\n----------\r\n");
		
		sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 2.转发请求"+toSend.readedLength+"字节完成\r\n");
		
		TcpReceiver recServer = recBytesFromSocket(dstrbSocket);
		
		
		sbLog.append(Format.DateTimeSSSFormat.format(new Date())+" 3.接收到响应："+recServer.readedLength+"字节\r\n");
		if(recServer.readedLength>=24){
			sbLog.append("头部："+new String(recServer.recBytes,0,24,"utf-8")+"\r\n");
		}
		return recServer;
	}
}
